<script setup lang="ts">
import { ElForm } from 'element-plus'
import { ObjectUtil } from '@utils/object-util'
import { Pages } from '@typings/pages'
import YkDatePicker from '@yk/components/date-picker/YkDatePicker.vue'
import YkTableColumn from '@yk/components/table-column/YkTableColumn.vue'
import YkPagination from '@yk/components/pagination/YkPagination.vue'
import { Download } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { ECharts, EChartsOption, LineSeriesOption } from 'echarts'
import { EChartsUtil, getLinesStyle } from '@utils/echarts'
import YkEmptyBox from '@yk/components/empty-box/YkEmptyBox.vue'
import { EmptyEnum, EmptyState } from '@yk/components/empty-box/type'
import { getVariableListByParamsAPI } from '@/api/variable'
import { DeviceDTO } from '@/api/entity/device'
import { VariableDTO, VariableVO } from '@/api/entity/variable'
import { getVariableHistoryByDateAPI } from '@/api/history'
import { TableUtil } from '@utils/table-util'
import { ServerEnum } from '@/api/enum/server'
import { LoadingSvg } from '@assets/styles/loading'

defineOptions({ name: 'DeviceHistoryData' })
const props = defineProps<{
  device: DeviceDTO
}>()

onMounted(() => {
  initDataLine()
})

// region TODO 查询
const searchParams = reactive({
  // 结束时间
  endTime: '',
  // 开始时间
  startTime: '',
  // 变量id
  variableIds: [],
  // 设备id
  tableName: ''
})
// 备份查询条件
const _searchParams = shallowRef<typeof searchParams>()
const usableUnit = computed(() => {
  const dataset = new Set<string>()
  for (let i = 0, len = searchParams.variableIds.length; i < len; i++) {
    if (dataset.size < 2) {
      dataset.add(variableMap.get(searchParams.variableIds[i]).unit)
    } else {
      break
    }
  }
  return dataset
})
function searchHandle () {
  if (searchParams.variableIds.length && searchParams.startTime && searchParams.endTime) {
    pages.pageNum = 1
    searchParams.tableName = props.device.id
    _searchParams.value = ObjectUtil.copy(searchParams)
    getHistoryData()
    // getTableData()
    // getDataLine()
  } else {
    ElMessage.info('请选择查询条件')
  }
}
// endregion

// region TODO 切换视图
const viewCheck = shallowRef<'chart' | 'table'>('chart')
function setViewActive (param: typeof viewCheck.value) {
  viewCheck.value = param
}
// endregion

// region TODO 获取历史数据 - 表格 & 折线
const historyDataLoading = shallowRef(false)
function getHistoryData () {
  historyDataLoading.value = true
  getVariableHistoryByDateAPI(searchParams).finally(() => {
    historyDataLoading.value = false
  }).then((res) => {
    res.result().then((rdata) => {
      // rdata.data = [
      //   {
      //     variableId: '1727942476968366081',
      //     variableVOList: [
      //       { ts: '2020-12-12 12:12:12', value: '220' },
      //       { ts: '2020-12-13 12:12:12', value: '221' },
      //       { ts: '2020-12-14 12:12:12', value: '219' },
      //       { ts: '2020-12-15 12:12:12', value: '222' }
      //     ]
      //   },
      //   {
      //     variableId: '1727942476968366082',
      //     variableVOList: [
      //       { ts: '2020-12-12 12:12:12', value: '223' },
      //       { ts: '2020-12-13 12:12:12', value: '222' },
      //       { ts: '2020-12-14 12:12:12', value: '210' },
      //       { ts: '2020-12-15 12:12:12', value: '220' }
      //     ]
      //   },
      //   {
      //     variableId: '1727942476968366083',
      //     variableVOList: [
      //       { ts: '2020-12-12 12:12:12', value: '1' },
      //       { ts: '2020-12-13 12:12:12', value: '1.2' },
      //       { ts: '2020-12-14 12:12:12', value: '1.5' },
      //       { ts: '2020-12-15 12:12:12', value: '2.2' }
      //     ]
      //   }
      // ]
      const data = rdata.data || []
      if (data.length) {
        // 格式化数据
        const dataDic: Record<string, VariableVO[]> = data.reduce((ret, item) => {
          ret[item.variableId] = item.variableVOList || []
          return ret
        }, {}) as any
        getDataLine(dataDic)
        getTableDataPool(dataDic)
      } else {
        dataLineState.value = EmptyEnum.EMPTY
        getTableDataPool({})
      }
    })
  })
}
// endregion

// region TODO 数据图
const dataLine = shallowRef<ECharts>()
const dataLineRef = shallowRef<HTMLDivElement>()
const dataLineState = ref<EmptyState>(EmptyEnum.NONE)
function initDataLine () {
  dataLine.value = echarts.init(dataLineRef.value)
  EChartsUtil.addResizeListener(dataLine.value)
}
function getDataLine (dataDic: Record<string, VariableVO[]>) {
  dataLine.value.clear()
  // 记录yAxis数据
  const yAxis: EChartsOption['yAxis'] = []
  // 获取单位数组
  const unitArr = Array.from(usableUnit.value)
  // 生成单位字典，方便根据单位获取yAxis的下标
  const unitDic = Array.from(usableUnit.value).reduce((ret, item, index) => {
    ret[item] = index
    return ret
  }, {})
  unitArr.forEach((item) => yAxis.push({ name: item }))
  // 记录names
  const names = []
  // 记录了series
  const series: LineSeriesOption[] = []
  // 循环变量获取各个数据
  _searchParams.value.variableIds.forEach(id => {
    // 拿到当前变量
    const variable = variableMap.get(id)
    // 拿到name
    names.push(variable.name)
    const data = dataDic[variable.id] || []
    // 根据变量生成曲线配置
    series.push({
      type: 'line',
      yAxisIndex: unitDic[variable.unit],
      data: data ? data.map(item => ([item.ts, item.value])) : []
    })
  })
  if (series.some(item => item.data.length)) {
    dataLine.value.setOption(getLinesStyle({ colors: [], names })
      .setGrid({ top: 80 })
      .setSeries(series)
      .setYAxis(yAxis).getResult())
    dataLineState.value = EmptyEnum.SUCCESS
  } else {
    dataLineState.value = EmptyEnum.EMPTY
  }
}
onBeforeUnmount(() => {
  EChartsUtil.removeResizeListener(dataLine.value)
})
// endregion

// region TODO 表格数据
const pages = reactive(new Pages())
const tableHeader = shallowRef([])
// 存储需要显示的当页数据
const tableData = shallowRef([])
// 表格数据池，存储所有数据
let tableDataPool = []
// 前端分页，加载所有数据
function getTableDataPool (dataDic: Record<string, VariableVO[]>) {
  const _tableHeader = []
  const _tableDataPool = {}
  _searchParams.value.variableIds.forEach((id) => {
    // 处理头部
    // 拿到当前变量
    const variable = variableMap.get(id)
    let label = variable.name
    variable.unit && (label += `(${variable.unit})`)
    _tableHeader.push({ prop: id, label })
    // 处理表格
    const data = dataDic[variable.id] || []
    for (let i = 0, len = data.length; i < len; i++) {
      const item = data[i]
      if (!_tableDataPool[item.ts]) {
        _tableDataPool[item.ts] = { time: item.ts }
      }
      _tableDataPool[item.ts][id] = item.value
    }
  })
  tableHeader.value = _tableHeader
  tableDataPool = Object.values(_tableDataPool).reverse() || []
  pages.pageNum = 1
  pages.total = tableDataPool.length
  getTableData()
}
function getTableData () {
  tableData.value = TableUtil.paging(tableDataPool, pages)
}
// endregion

// region TODO 变量列表
const variableList = shallowRef<VariableDTO[]>([])
const variableMap = new Map<string, VariableDTO>()
// 获取变量列表
function getVariableList () {
  getVariableListByParamsAPI({ deviceId: props.device.id, storage: '1' }).then((res) => {
    res.result().then((rdata) => {
      variableMap.clear()
      variableList.value = rdata.data
      variableList.value.forEach((item) => {
        variableMap.set(item.id, item)
      })
    })
  })
}

// endregion

// region TODO 监听设备发生变化
watch(() => props.device, (nv, ov) => {
  if (props.device && nv.id !== ov?.id) {
    getVariableList()
    searchParams.variableIds = []
    _searchParams.value = null
  }
}, { immediate: true })
// endregion
</script>

<template>
  <div class="wh-100 c_card-white">
    <div class="c_card_header">
      <div class="c_card-title">历史数据</div>
      <div class="c_header_right">
        <el-link href="/#/data/custom-report" type="primary">
          <span class="color-primary">自定义报表</span>
        </el-link>
      </div>
    </div>
    <!--搜索表单-->
    <el-form inline class="c_form-search" @submit.prevent="searchHandle">
      <el-form-item>
        <div>
          <el-select
            v-model="searchParams.variableIds" placeholder="选择变量" multiple
            collapse-tags
            collapse-tags-tooltip
          >
            <template #header>
              <p class="c_form-tip fs-12">支持选择两种不同单位的变量</p>
            </template>
            <el-option
              v-for="item in variableList" :key="item.id" :label="item.name"
              :value="item.id"
              :disabled="usableUnit.size === 2 && !usableUnit.has(item.unit)"
            >
              <div class="d-flex-between-center">
                <div>{{ item.name }}</div>
                <div class="text-color-placeholder fs-12">{{ item.unit }}</div>
              </div>
            </el-option>
          </el-select>
        </div>
      </el-form-item>
      <el-form-item>
        <yk-date-picker v-model:start="searchParams.startTime" v-model:end="searchParams.endTime" type="datetimerange" :days="7" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="searchHandle">查询</el-button>
      </el-form-item>
    </el-form>
    <yk-empty-box :state="_searchParams ? true : { type: EmptyEnum.EMPTY_VAR, description: '请选择查询条件' }" style="height: calc(100% - 80px);">
      <div v-loading="historyDataLoading" :element-loading-svg="LoadingSvg" class="h-100">
        <!--功能栏-->
        <div class="position-relative">
          <div class="control-strip position-absolute" style="z-index: 20">
            <div class="control-strip__item" :class="{ 'is-active' : viewCheck === 'chart' }" @click="setViewActive('chart')">
              <ic-data-line class="icon" />
              <span>数据图</span>
            </div>
            <div class="control-strip__item" :class="{ 'is-active' : viewCheck === 'table' }" @click="setViewActive('table')">
              <ic-data-table class="icon" />
              <span>表格</span>
            </div>
          </div>
        </div>
        <!--数据图-->
        <yk-empty-box v-show="viewCheck === 'chart'" :state="dataLineState" class="h-100">
          <div ref="dataLineRef" class="h-100" />
        </yk-empty-box>
        <!--表格-->
        <div
          v-if="viewCheck === 'table'" v-loading="historyDataLoading" v-ref-height
          :element-loading-svg="LoadingSvg"
          class="h-100"
        >
          <div class="text-right">
            <export-file url="/dataOperation/dynamicHeadExport" :params="_searchParams" :server="ServerEnum.DataGatherer">
              <el-button class="c_btn--export" :icon="Download as any">导出</el-button>
            </export-file>
          </div>
          <!--表格-->
          <el-table
            class="c_table-page w-100 mt-16" stripe
            :data="tableData"
            max-height="calc(var(--ref-height) - 93px)"
          >
            <el-table-column label="#" type="index" fixed :index="TableUtil.indexMethod.bind(this, pages)" />
            <yk-table-column label="采集时间" prop="time" sortable fixed />
            <yk-table-column
              v-for="item in tableHeader" :key="item.prop" :label="item.label"
              :prop="item.prop"
              sortable
            />
          </el-table>
          <!--分页-->
          <yk-pagination class="c_table-pagination-page" :pages="pages" @handle="getTableData" />
        </div>
      </div>
    </yk-empty-box>
  </div>
</template>

<style scoped lang="scss">
.control-strip {
  background-color: #F7F8FA;
  padding: 4px;
  border-radius: 2px;
  display: inline-flex;
  .control-strip__item {
    padding: 4px 16px;
    border-radius: 2px;
    color: var(--el-text-color-regular);
    @include d-flex(center);
    font-size: 14px;
    cursor: pointer;
    .icon {
      margin-right: 4px;
      font-size: 16px;
    }
    &.is-active {
      color: var(--el-color-primary);
      background-color: white;
    }
  }
}
</style>
